import type { API } from "@/types/api";
import type { TreeDataNode } from "antd";
import { useNavigate } from "react-router-dom";
import { DownOutlined } from "@ant-design/icons";
import { Tree, Input, Spin, message } from "antd";
import { postLookFileContext } from "@/services/hosting/api";
import React, { useState, useEffect, useMemo, useCallback } from "react";

const { Search } = Input;

interface FileTreeViewerProps {
    getCodeContent?: (values: API.PostJarContext) => Promise<void>;
    setFileName: (fileName: string) => void;
    appId: string;
    stype: string;
    setFilePath: (filePath: string) => void; // 确保这个prop被正确定义
    loading?: boolean;
}

interface ExtendedTreeDataNode extends TreeDataNode {
    path: string;
    type: string;
    name: string;
    children?: ExtendedTreeDataNode[];
}

const FileTreeViewer: React.FC<FileTreeViewerProps> = ({
    getCodeContent,
    setFileName,
    appId,
    stype,
    setFilePath,
    loading,
}) => {
    const navigate = useNavigate();
    const [treeData, setTreeData] = useState<ExtendedTreeDataNode[]>([]);
    const [innerLoading, setInnerLoading] = useState(false);
    const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
    const [searchValue, setSearchValue] = useState("");
    const [autoExpandParent, setAutoExpandParent] = useState(true);
    const [selectedNode, setSelectedNode] = useState<React.Key | null>(null);
    const nodeId = new URLSearchParams(window.location.search).get("nodeId") as string;
    const getFirstTwoLevelKeys = useCallback(
        (
            nodes: ExtendedTreeDataNode[],
            level = 0,
            keys: React.Key[] = [],
        ): React.Key[] => {
            if (level > 1) return keys;

            nodes.forEach((node) => {
                keys.push(node.key);
                if (node.children && level < 1) {
                    getFirstTwoLevelKeys(node.children, level + 1, keys);
                }
            });
            return keys;
        },
        [],
    );

    const fetchJarStructure = useCallback(async () => {
        setInnerLoading(true);
        try {
            const response = await postLookFileContext(
                {
                    app_id: appId,
                    path: "",
                    mode: "tree",
                },
                stype,
                nodeId,
                navigate,
            );
            const processData = (data: any[]): ExtendedTreeDataNode[] => {
                return data.map((item) => ({
                    key:
                        item.key ||
                        item.path ||
                        Math.random().toString(36).substring(2, 9),
                    title: item.title || item.name,
                    name: item.name || item.title,
                    path: item.path,
                    type: item.type,
                    children: item.children
                        ? processData(item.children)
                        : undefined,
                    isLeaf: !item.children || item.type !== "dir",
                }));
            };
            const processedData = processData(
                Array.isArray(response.message) ? response.message : [],
            );
            setTreeData(processedData);
            if (processedData.length > 0) {
                const keysToExpand = getFirstTwoLevelKeys(processedData);
                // 使用 setTimeout 确保在 DOM 更新后再展开节点
                setTimeout(() => {
                    setExpandedKeys(keysToExpand);
                    setAutoExpandParent(false);
                }, 0);
            }
        } catch (error: any) {
            console.error("Error:", error);
            message.error(error.message);
        } finally {
            setInnerLoading(false);
        }
    }, [appId, navigate, getFirstTwoLevelKeys]);

    const onLoadData = useCallback(
        async ({ key }: { key: React.Key }) => {
            try {
                const response = await postLookFileContext(
                    {
                        app_id: appId,
                        path: key.toString(),
                        mode: "tree",
                    },
                    stype,
                    nodeId,
                    navigate,
                );

                const processChildren = (
                    data: any[],
                ): ExtendedTreeDataNode[] => {
                    return data.map((item) => ({
                        key:
                            item.key ||
                            item.path ||
                            Math.random().toString(36).substring(2, 9),
                        title: item.title || item.name,
                        name: item.name || item.title,
                        path: item.path,
                        type: item.type,
                        children: item.children
                            ? processChildren(item.children)
                            : undefined,
                        isLeaf: !item.children || item.type !== "dir",
                    }));
                };

                const children = processChildren(
                    Array.isArray(response.message) ? response.message : [],
                );

                setTreeData((prevData) => {
                    const updateNode = (
                        nodes: ExtendedTreeDataNode[],
                    ): ExtendedTreeDataNode[] => {
                        return nodes.map((node) => {
                            if (node.key === key) {
                                return {
                                    ...node,
                                    children,
                                    isLeaf: children.length === 0,
                                };
                            }
                            if (node.children) {
                                return {
                                    ...node,
                                    children: updateNode(node.children),
                                };
                            }
                            return node;
                        });
                    };
                    return updateNode(prevData);
                });

                return Promise.resolve();
            } catch (error) {
                console.error("Error loading node data:", error);
                return Promise.reject(error);
            }
        },
        [appId, navigate],
    );

    const onSearchChange = useCallback(
        (e: React.ChangeEvent<HTMLInputElement>) => {
            const { value } = e.target;
            setSearchValue(value);

            if (!value) {
                setExpandedKeys([]);
                return;
            }

            const getParentKey = (
                key: React.Key,
                tree: ExtendedTreeDataNode[],
            ): React.Key | null => {
                for (let i = 0; i < tree.length; i++) {
                    const node = tree[i];
                    if (node.children) {
                        if (node.children.some((item) => item.key === key)) {
                            return node.key;
                        }
                        const foundKey = getParentKey(key, node.children);
                        if (foundKey) return foundKey;
                    }
                }
                return null;
            };

            const newExpandedKeys = treeData.reduce<React.Key[]>(
                (acc, node) => {
                    const traverse = (node: ExtendedTreeDataNode): boolean => {
                        const title = node.title as string;
                        if (title.toLowerCase().includes(value.toLowerCase())) {
                            const parentKey = getParentKey(node.key, treeData);
                            if (parentKey && !acc.includes(parentKey)) {
                                acc.push(parentKey);
                            }
                            return true;
                        }
                        if (node.children) {
                            return node.children.some(traverse);
                        }
                        return false;
                    };
                    traverse(node);
                    return acc;
                },
                [],
            );

            setExpandedKeys(newExpandedKeys);
            setAutoExpandParent(true);
        },
        [treeData],
    );

    const handleNodeClick = useCallback(
        (node: ExtendedTreeDataNode) => {
            const fileName =
                node.name ||
                (typeof node.title === "string"
                    ? node.title
                    : node.key.toString());

            if (setFileName) {
                setFileName(fileName);
            }

            // 设置文件路径
            if (setFilePath) {
                setFilePath(node.path);
            }

            if (node.type !== "dir" && getCodeContent) {
                setSelectedNode(node.key);
                getCodeContent({
                    app_id: appId,
                    path: node.path,
                    mode: "value",
                });
            } else {
                const isExpanded = expandedKeys.includes(node.key);
                setExpandedKeys(
                    isExpanded
                        ? expandedKeys.filter((key) => key !== node.key)
                        : [...expandedKeys, node.key],
                );
                setAutoExpandParent(false);
            }
        },
        [appId, getCodeContent, setFileName, setFilePath, expandedKeys],
    );

    const handleExpand = useCallback((keys: React.Key[]) => {
        setExpandedKeys(keys);
        setAutoExpandParent(false);
    }, []);

    const processedTreeData = useMemo(() => {
        const loop = (data: ExtendedTreeDataNode[]): ExtendedTreeDataNode[] =>
            data.map((item) => {
                const strTitle = item.title as string;
                const index = strTitle
                    .toLowerCase()
                    .indexOf(searchValue.toLowerCase());

                const title =
                    index > -1 ? (
                        <span>
                            {strTitle.substring(0, index)}
                            <span style={{ color: "#f50" }}>{searchValue}</span>
                            {strTitle.substring(index + searchValue.length)}
                        </span>
                    ) : (
                        <span>{strTitle}</span>
                    );

                return {
                    ...item,
                    title,
                    children: item.children ? loop(item.children) : undefined,
                };
            });

        return loop(treeData);
    }, [treeData, searchValue]);

    useEffect(() => {
        fetchJarStructure();
    }, [fetchJarStructure]);

    return (
        <div
            style={{
                width: "100%",
                height: "100%",
                borderRadius: "4px",
                backgroundColor: "#fff",
                display: "flex",
                flexDirection: "column",
                padding: "8px 0",
            }}
        >
            <div
                style={{
                    padding: "0 16px 0px",
                    // borderBottom: "1px solid #f0f0f0",
                }}
            >
                <Search
                    placeholder="搜索文件/目录"
                    onChange={onSearchChange}
                    allowClear
                    style={{ marginBottom: 0 }}
                />
            </div>

            {loading || innerLoading ? (
                <div
                    style={{
                        flex: 1,
                        display: "flex",
                        justifyContent: "center",
                        alignItems: "center",
                    }}
                >
                    <Spin size="large" tip="加载文件结构中..." />
                </div>
            ) : (
                <div
                    style={{
                        flex: 1,
                        overflow: "auto",
                        padding: "8px 0 0",
                    }}
                >
                    <Tree
                        showLine
                        switcherIcon={
                            <DownOutlined
                                style={{
                                    fontSize: 12,
                                    color: "#666",
                                    transition: "transform 0.3s",
                                }}
                            />
                        }
                        treeData={processedTreeData}
                        expandedKeys={expandedKeys}
                        onExpand={handleExpand}
                        loadData={onLoadData}
                        autoExpandParent={autoExpandParent}
                        selectedKeys={selectedNode ? [selectedNode] : []}
                        style={{
                            width: "100%",
                            minWidth: "fit-content",
                            fontFamily:
                                "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif",
                            fontSize: 14,
                            lineHeight: "24px",
                        }}
                        // indent={12}
                        titleRender={(node) => (
                            <div
                                style={{
                                    display: "flex",
                                    alignItems: "center",
                                    width: "100%",
                                    height: "24px",
                                    padding: "0 4px",
                                    cursor: "pointer",
                                    backgroundColor:
                                        selectedNode === node.key
                                            ? "#e6f7ff"
                                            : "transparent",
                                    // @ts-ignore
                                    ":hover": {
                                        backgroundColor: "#f5f5f5",
                                    },
                                }}
                                onClick={() =>
                                    handleNodeClick(
                                        node as ExtendedTreeDataNode,
                                    )
                                }
                            >
                                {typeof node.title === "function"
                                    ? node.title(node)
                                    : node.title}
                            </div>
                        )}
                        blockNode
                    />
                </div>
            )}
        </div>
    );
};

export default FileTreeViewer;